package org.jeecg.modules.wlhy.report;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.util.DateUtils;
import org.jeecg.common.util.ImageCompressUtil;
import org.jeecg.common.util.LngLonUtil;
import org.jeecg.modules.third.amap.service.HyShippingNoteAmapService;
import org.jeecg.modules.third.dongjiang.tax.system.constant.TaxConstant;
import org.jeecg.modules.third.dongjiang.tax.system.dto.ApiBaseResDTO;
import org.jeecg.modules.third.amap.dto.GpsDTO;
import org.jeecg.modules.third.dongjiang.tax.system.dto.req.order.OrderDTO;
import org.jeecg.modules.third.dongjiang.tax.system.service.DongjiangTaxSystemService;
import org.jeecg.modules.third.openapi.WaybillRouteService;
import org.jeecg.modules.wlhy.bill.entity.HyShippingNoteBill;
import org.jeecg.modules.wlhy.bill.service.IHyShippingNoteBillService;
import org.jeecg.modules.wlhy.customer.entity.HyCustomer;
import org.jeecg.modules.wlhy.customer.service.impl.HyCustomerServiceImpl;
import org.jeecg.modules.wlhy.hydriver.entity.HyDriver;
import org.jeecg.modules.wlhy.hydriver.service.impl.HyDriverServiceImpl;
import org.jeecg.modules.wlhy.hyvehicle.entity.HyVehicle;
import org.jeecg.modules.wlhy.hyvehicle.service.impl.HyVehicleServiceImpl;
import org.jeecg.modules.wlhy.order.entity.HyOrder;
import org.jeecg.modules.wlhy.order.service.impl.HyOrderServiceImpl;
import org.jeecg.modules.wlhy.setting.service.IHySettingService;
import org.jeecg.modules.wlhy.shipping.entity.HyShippingNote;
import org.jeecg.modules.wlhy.shipping.entity.PointDataListVO;
import org.jeecg.modules.wlhy.shipping.entity.TaxUpDataShippingNoteDTO;
import org.jeecg.modules.wlhy.shipping.entity.WaybillRouteVO;
import org.jeecg.modules.wlhy.shipping.mapper.HyShippingNoteMapper;
import org.jeecg.modules.wlhy.shipping.service.IHyShippingNoteService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.File;
import java.math.BigDecimal;
import java.util.*;

@Service
public class TjReportService {
    private static final Logger LOGGER = LoggerFactory.getLogger(TjReportService.class);
    @Autowired
    private IHyShippingNoteService hyShippingNoteService;

    @Resource
    private HyShippingNoteMapper hyShippingNoteMapper;

    @Autowired
    private HyOrderServiceImpl orderService;

    @Autowired
    private HyCustomerServiceImpl customerService;

    @Autowired
    private HyDriverServiceImpl driverService;

    @Autowired
    private HyVehicleServiceImpl vehicleService;

    @Resource
    private IHySettingService settingService;

    @Autowired
    private HyShippingNoteAmapService shippingNoteAmapService;

    @Autowired
    private IHyShippingNoteBillService hyShippingNoteBillService;


    @Autowired
    private DongjiangTaxSystemService dongjiangTaxSystemService;

    @Autowired
    private WaybillRouteService waybillRouteService;

//    @Autowired
//    private IHyBillService hyBillService;


    @Value(value = "${jeecg.path.upload}")
    private String uploadpath;


    /**
     * 运单上报税务系统
     *
     * @param hyShippingNote
     * @return
     */
    public ApiBaseResDTO uploadTax(HyShippingNote hyShippingNote) throws Exception {

        HyShippingNote ShippingNoteDb = hyShippingNoteService.getById(hyShippingNote.getId());

        if (ShippingNoteDb == null) {
            throw new JeecgBootException("未找到对应数据");
        }
        Integer second = DateUtils.getDifferentDaysByMillisecond(ShippingNoteDb.getStatusDtLoading(), ShippingNoteDb.getStatusDtUnloading());
        if (second < 60 * 60) {
            Calendar rightNow = Calendar.getInstance();
            rightNow.setTime((ShippingNoteDb.getStatusDtLoading()));
            rightNow.add(Calendar.HOUR_OF_DAY, -1);//日期减1小时
            ShippingNoteDb.setStatusDtLoading(rightNow.getTime());

            Calendar rightNow2 = Calendar.getInstance();
            rightNow2.setTime((ShippingNoteDb.getStatusDtReceive()));
            rightNow2.add(Calendar.HOUR_OF_DAY, -1);//日期减1小时
            ShippingNoteDb.setStatusDtReceive(rightNow2.getTime());
        }
        //        if (!ShippingNoteDb.getOrderMode().equals("1")) {
        //            throw new JeecgBootException("该运单非管理模式，不能上报");
        //        }
        OrderDTO orderDTO = shippingNoteTOOrderDTO(ShippingNoteDb);
        if (orderDTO == null) {
            throw new JeecgBootException("未找到对应数据");
        }
        ApiBaseResDTO reportResult = dongjiangTaxSystemService.sendOrder(orderDTO);
        Integer code = reportResult != null && StringUtils.isNotEmpty(reportResult.getCode()) ? Integer.valueOf(reportResult.getCode()) : 0;
        ShippingNoteDb.setTaxUploadStatus(code >= 100 && code < 200 ? "1" : "2");
        ShippingNoteDb.setTaxFailureReason(reportResult.getDesc());
        ShippingNoteDb.setTaxUploadDate(new Date());
        hyShippingNoteService.updateById(ShippingNoteDb);
        return reportResult;

    }

    /**
     * 组装税务系统运单信息
     *
     * @param hyShippingNote
     * @return
     */
    private OrderDTO shippingNoteTOOrderDTO(HyShippingNote hyShippingNote) {
        if (hyShippingNote == null) {
            throw new JeecgBootException("未找到对应数据");
        }
        HyCustomer hyCustomer = customerService.getById(hyShippingNote.getCustomerId());
        if (hyCustomer == null) {
            throw new JeecgBootException("该运单货主信息不能为空");
        }

        HyOrder hyOrder = orderService.getById(hyShippingNote.getOrderId());
        if (hyOrder == null) {
            throw new JeecgBootException("该运单货源信息不能为空");
        }

        HyDriver hyDriver = driverService.getById(hyShippingNote.getDriverId());
        if (hyDriver == null) {
            throw new JeecgBootException("该运单司机信息不能为空");
        }
        HyVehicle hyVehicle = vehicleService.getById(hyShippingNote.getVehicleId());
        if (hyVehicle == null) {
            throw new JeecgBootException("该运单车辆信息不能为空");
        }

        LambdaQueryWrapper<HyShippingNoteBill> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(HyShippingNoteBill::getShippingId, hyShippingNote.getId());
        queryWrapper.eq(HyShippingNoteBill::getBillType, "1");
        HyShippingNoteBill hyShippingNoteBill = hyShippingNoteBillService.getOne(queryWrapper);
        if (hyShippingNoteBill == null) {
            throw new JeecgBootException("该运单运费流水单信息不能为空");
        }
        OrderDTO orderDTO = new OrderDTO();

        orderDTO.setDdbh(TaxConstant.API_TAX_CUSTOMER_SUBFIX + hyShippingNote.getShippingNoteNumber());// 是 发布方订单编号（ddbh 默 认长度 32 位，建议以平台 缩写大写字母作为前缀， 并结合数字+字母混合形 成 32 位唯一标识）
        orderDTO.setDduuid(TaxConstant.API_TAX_CUSTOMER_SUBFIX + hyShippingNote.getId());// 是 订单唯一标识，由平台生 成订单唯一标识，在服务 方订单中需要使用该唯一 标识（uuid 默认长度 32 位，建议以平台缩写大写 字母作为前缀，并结合数 字+字母混合形成 32 位唯 一标识）
        if (StringUtils.isNotEmpty(hyCustomer.getFbfuuid())) {
            orderDTO.setFbfuuid(hyCustomer.getFbfuuid());
        } else {
            orderDTO.setFbfuuid(TaxConstant.API_TAX_CUSTOMER_SUBFIX + hyCustomer.getId());
        }
        orderDTO.setFbfxm("");// 否 发布方联系人姓名
        orderDTO.setFbfsfzjhm("");// 否 发布方联系人身份证件号 码
        orderDTO.setFbfnsrmc(hyCustomer.getCustomerName());// 是 发布方企业名称
        orderDTO.setFbfnsrsbh(hyCustomer.getCreditCode());// 是 发布方企业纳税人识别号
        //1 是 发单时间（2019-03-20 14:54:31）
        orderDTO.setFdsj(DateUtils.dateTimeToString(hyOrder.getCreateTime()));
        //2 是 接单时间-服务方接单 签订协议时间（时间格 式：yyyy-MM-dd HH：mm： ss
        orderDTO.setJdsj(DateUtils.dateTimeToString(hyShippingNote.getStatusDtReceive()));
        orderDTO.setFdfs("PC");// 是 发单方式（PC、手机）

        //####### 发布方（货主）订单金额
        BigDecimal costPayTotal = hyShippingNote.getCustomerFee();
        //核算信息费
//        if("1".equals(hyShippingNote.getIzInformationFeeOpenInvoicing())){
//            costPayTotal = costPayTotal.add(hyShippingNote.getInformationFee());
//        }
        orderDTO.setFbfddje(String.format("%.2f", costPayTotal));// (18,2 ) 是 发布方（货主）订单金 额
        if (StringUtils.isNotEmpty(hyDriver.getFwfuuid())) {
            orderDTO.setFwfuuid(hyDriver.getFwfuuid());
        } else {
            orderDTO.setFwfuuid(TaxConstant.API_TAX_CUSTOMER_SUBFIX + hyDriver.getId());
        }

        orderDTO.setFwfxm(hyDriver.getDriverName());// 是 服务方（车主）姓名
        orderDTO.setFwfsfzjlx("201");// 是 身份证件类型-填写身 份证件种类代码，参见 《申报表-计税 excel页 签：证件代码表》 2019-5-15 说明
        orderDTO.setFwfsfzjhm(hyDriver.getIdcard());// 是 服务方（车主）身份证 件号码

        int second = DateUtils.getDifferentDaysByMillisecond(hyShippingNote.getStatusDtLoading(),
                hyShippingNote.getStatusDtUnloading());
        int days = 1;

        if (second > 86400) {
            BigDecimal diff = new BigDecimal(second * 1000).divide(new BigDecimal(86400000), 7, BigDecimal.ROUND_HALF_UP);
            days = (int) Math.ceil(diff.doubleValue());
        }


        orderDTO.setFwsj(days + "天");// 是 起点到终点间运输服务 时长（以小时为单位， 比如 1小时、1天 3小时） （2019-5-10 说明） 2019-5-10 说明
        //3 是 起始运输时间-运输货物发车时间
        orderDTO.setQsfwsj(DateUtils.dateTimeToString(hyShippingNote.getStatusDtLoading()));
        //4 是 结束运输时间-车辆到 达目的地时间
        orderDTO.setJsfwsj(DateUtils.dateTimeToString(hyShippingNote.getStatusDtUnloading()));
        orderDTO.setSfd(hyShippingNote.getSendAreaCode());// 是 起运地（始发地）-填写 行政区划代码（市级）， 参见《行政区划代码-名 称表》 2019-5-15 说明
        orderDTO.setMdd(hyShippingNote.getReceiveAreaCode());// 是 到达地（目的地）-填写 行政区划代码（市级）， 参见《行政区划代码-名 称表》 2019-5-15 说明
        orderDTO.setSfdxxdz(hyShippingNote.getSendAddress());// 是 始发地详细地址
        orderDTO.setMddxxdz(hyShippingNote.getReceiveAddress());// 是 目的地详细地址

        Integer[] cycc = new Integer[3];
        cycc[0] = StringUtils.isNotEmpty(hyVehicle.getVehicleLong()) ? Integer.parseInt(hyVehicle.getVehicleLong()) / 1000 : 0;
        cycc[1] = StringUtils.isNotEmpty(hyVehicle.getVehicleWidth()) ? Integer.parseInt(hyVehicle.getVehicleWidth()) / 1000 : 0;
        cycc[2] = StringUtils.isNotEmpty(hyVehicle.getVehicleHeight()) ?
                Integer.parseInt(hyVehicle.getVehicleHeight()) / 1000 : 0;
        double cyccInt = cycc[0] * cycc[1] * cycc[2];
        orderDTO.setCc(String.format("%.2f", cyccInt));// (18,2 ) 是 车长（数量+单位 m/米 长*宽*高）

        orderDTO.setCx(hyVehicle.getVehicleType());//  是 车型（推送文字）
        orderDTO.setCycph(hyVehicle.getVehicleNumber());//是 承运车牌号 2019-8-2 新增
        orderDTO.setHwzl(String.format("%.2f", hyShippingNote.getGoodsWeightLoading()));// (18,2 ) 是 货物重量（t/吨）
        orderDTO.setHwtj(hyShippingNote.getCube() != null ? String.format("%.2f", hyShippingNote.getCube()) : "00.00");// (18,2 ) 是 货物体积（方）
        orderDTO.setHwdw("吨");// 是 货物单位（吨、方）
        orderDTO.setHwmc(hyShippingNote.getDescriptionOfGoods());// 是 所运货物（货物名称）
        orderDTO.setHyxje(String.valueOf(0.00));// (18,2 ) 是 货运险金额（如果不存 在，默认填写 0） 2020-11-1 说明
        //####### 服务方货物运费金额
        BigDecimal costPayShipping = hyShippingNote.getDriverFee();

        orderDTO.setFwfddje(String.format("%.2f", costPayShipping));// (18,2 ) 是 服务方货物运费金额
        orderDTO.setHwsshy("5431");// 是 货物所属行业-填写行 业代码，参见《行业代 码-名称表》 2019-5-15 说明
        orderDTO.setJdfs("手机");// 20 是 接单方式（PC、手机）

        double m = LngLonUtil.GetDistance(hyShippingNote.getSendLatitude(), hyShippingNote.getSendLongitude(),
                hyShippingNote.getReceiveLatitude(), hyShippingNote.getReceiveLongitude());
        double km = Math.round((m / 100d) / 10d);
        orderDTO.setLc(String.format("%.2f", km));//  是 路程（公里数）
        orderDTO.setZxfs("一装一卸");// 是 装卸方式（一装一卸 一装两卸）
        orderDTO.setPtfwf(String.valueOf(0.0));// (18,2 ) 是 平台服务费（平台企业自 定，没有默认填写 0） 2020-11-1 说明
        orderDTO.setZk(String.valueOf(0.0));// (18,2 ) 是 货主折扣（平台企业自定， 没有默认填写 0） 2020-11-1 说明
        orderDTO.setZffs("系统内虚拟货币支付");// 是 支付方式（银行卡支付、 微信支付、支付宝支付、 系统内虚拟货币支付） 2019-5-22 说明
        orderDTO.setHwspbm("");// 否 货物商品编码
        orderDTO.setQtjl("");//否 其他奖励（油费、卡费 等）

        orderDTO.setZfpz(hyShippingNoteBill.getBillNum());// 是 支付凭证（支付流水号）
        orderDTO.setYhkh(hyShippingNoteBill.getCraccno() + hyShippingNoteBill.getCrlogaccno());// 是 银行卡号（银行卡号（微 信账号、支付宝账号）） 2019-5-22 说明
        orderDTO.setYhls(hyShippingNoteBill.getBillNum());// 是 银行流水-资金流水
        //5 是 订单结束时间-最终结算时间 时间格式：yyyy-MM-dd HH:mm:ss
        orderDTO.setJssj(DateUtils.dateTimeToString(hyShippingNote.getPayDt()));
        orderDTO.setSkrxm(hyShippingNoteBill.getCraccname());// 是 收款人姓名，指订单完 成时，收到款项的人的 姓名 2019-7-9 说明
        orderDTO.setSkrsfzjhm(hyShippingNoteBill.getActualCarrierId());// 是 收款人身份证件号码， 指订单完成时，收到款 项的人的身份证号码 2019-7-9 说明


        String vehicleTrackSwitch = settingService.getSettingValueByTag2("vehicle_track_switch");

        List<GpsDTO> gpsDTOs = new ArrayList<>();
        if (StringUtils.equals("1", vehicleTrackSwitch)) {
            gpsDTOs = this.getListGps(hyVehicle, hyShippingNote);
            if (CollectionUtils.isEmpty(gpsDTOs)) {
                gpsDTOs = shippingNoteAmapService.getMapGps(hyShippingNote);
            }
        } else {
            gpsDTOs = shippingNoteAmapService.getMapGps(hyShippingNote);
        }
        if (CollectionUtils.isEmpty(gpsDTOs)) {
            throw new JeecgBootException("该运单轨迹信息不能为空");
        }

        orderDTO.setGps(JSONObject.toJSONString(gpsDTOs));// 是 从货物运输发车开始到 目的地之间的 GPS 或北 斗运输轨迹【GPS 统一标 准为火星坐标系 (GCJ-02) 】,推送数据 需拼接成 json数组格式 后，转成字符串推送： "gps":"[{\"lat\":\"3 8.538010368599704\", \"lon\":\"112.068393 46026618\",\"positio nTime\":\"2019-07-03 10:19:01\"},{\"lat\" :\"30.53760840433267 \",\"lon\":\"104.068 57044530535\",\"posi tionTime\":\"2019-07 -0310:22:58\"},…]" 2019-7-9 说明
        orderDTO.setDdjsssqy("");// 否 订单接收所属区域

        List<String> loadingSceneImgBase64S = new ArrayList<>();
        if (StringUtils.isNotBlank(hyShippingNote.getLoadingSceneImg())) {
            String loadingSceneImgBase64 = ImageCompressUtil.compressSrcImageToBase64(uploadpath + File.separator + hyShippingNote.getLoadingSceneImg(), 500);
            loadingSceneImgBase64S.add(loadingSceneImgBase64);
        }
        orderDTO.setXczhfj(loadingSceneImgBase64S);// 是 现场装货照片, 图片尺寸见补充说明,照片要 求进行 base64 转码传 输,图片需要拼接成 JSON 数组格式： "xczhfj": ["data:image/jpg;bas e64,编码"]

        List<String> unloadingSceneImgBase64S = new ArrayList<>();
        if (StringUtils.isNotBlank(hyShippingNote.getUnloadingSceneImg())) {
            String unloadingSceneImgBase64 = ImageCompressUtil.compressSrcImageToBase64(uploadpath + File.separator + hyShippingNote.getUnloadingSceneImg(), 500);
            unloadingSceneImgBase64S.add(unloadingSceneImgBase64);
        }
        orderDTO.setXcxhfj(unloadingSceneImgBase64S);// 是 现场卸货照片, 图片尺 寸见补充说明,照片要 求进行 base64 转码传 输,图片需要拼接成 JSON 数组格式： "xcxhfj": ["data:image/jpg;bas e64,编码"] 2019-7-9 新增

        List<String> imgLoadings = Arrays.asList(hyShippingNote.getImgLoading().split(","));
        List<String> imgLoadingBase64S = new ArrayList<>();
        for (String tmpimg : imgLoadings) {
            String imgLoadingBase64 = ImageCompressUtil.compressSrcImageToBase64(uploadpath + File.separator + tmpimg, 500);
            imgLoadingBase64S.add(imgLoadingBase64);
        }

        orderDTO.setThdfj(imgLoadingBase64S);// 是 提货单, 图片尺寸见补 充说明,照片要求进行 base64 转码传输,图片 需要拼接成JSON数组格 式："thdfj": ["data:image/jpg;bas e64,编码"] 2019-7-9 新增

        List<String> imgUnloadings = Arrays.asList(hyShippingNote.getImgUnloading().split(","));
        List<String> imgUnloadingBase64s = new ArrayList<>();
        for (String tmpUnImg : imgUnloadings) {
            String imgUnloadingBase64 = ImageCompressUtil.compressSrcImageToBase64(uploadpath + File.separator + tmpUnImg, 500);
            imgUnloadingBase64s.add(imgUnloadingBase64);
        }
        orderDTO.setRkdfj(imgUnloadingBase64s);// 是 入库单, 图片尺寸见补 充说明,照片要求进行 base64 转码传输,图片 需要拼接成JSON数组格 式："rkdfj": ["data:image/jpg;base64,编码"]

        return orderDTO;
    }

    /**
     * 税务上报获取运单轨迹gps数据
     *
     * @param hyVehicle
     * @param hyShippingNote
     * @return
     */
    private List<GpsDTO> getListGps(HyVehicle hyVehicle, HyShippingNote hyShippingNote) {
        List<GpsDTO> gpsDTOS = new ArrayList<>();

        try {
            //       Calendar calendar = new GregorianCalendar();
            //       calendar.setTime(hyShippingNote.getStatusDtUnloading());
            //       calendar.add(calendar.DATE,-1); //把日期往后增加一天,整数  往后推,负数往前移动
            //       Date startDateTime  = calendar.getTime(); //这个时间就是日期往前推一天的结果
            String startTime = DateUtils.dateTimeToString(hyShippingNote.getStatusDtLoading());
            String endTime = DateUtils.dateTimeToString(hyShippingNote.getStatusDtUnloading());
            String vehicleColor = StringUtils.isNotEmpty(hyVehicle.getVehiclePlateColorCode()) ? hyVehicle.getVehiclePlateColorCode() : "2";
            WaybillRouteVO waybillRouteVO = waybillRouteService.getWaybillRoute(hyVehicle.getVehicleNumber(), vehicleColor, startTime, endTime, "GCJ02");
            if (waybillRouteVO != null && CollectionUtils.isNotEmpty(waybillRouteVO.getPointDataList())) {
                List<PointDataListVO> pointDataListVOS = waybillRouteVO.getPointDataList();
                Integer a = pointDataListVOS.size();

                if (a <= 1000) {
                    for (PointDataListVO pointDataListVO : pointDataListVOS) {
                        GpsDTO gpsDTO = new GpsDTO();
                        gpsDTO.setLon(pointDataListVO.getLng());
                        gpsDTO.setLat(pointDataListVO.getLat());
                        gpsDTO.setPositionTime(pointDataListVO.getReceiveTime());
                        gpsDTOS.add(gpsDTO);
                    }
                } else {
                    Integer b = this.getFrequency(a);
                    Integer n = 1;
                    for (PointDataListVO pointDataListVO : pointDataListVOS) {
                        if (n % b == 0) {
                            GpsDTO gpsDTO = new GpsDTO();
                            gpsDTO.setLon(pointDataListVO.getLng());
                            gpsDTO.setLat(pointDataListVO.getLat());
                            gpsDTO.setPositionTime(pointDataListVO.getReceiveTime());
                            gpsDTOS.add(gpsDTO);
                        }
                        n++;
                    }
                }

            }
            return gpsDTOS;
        } catch (Exception e) {
            LOGGER.info("TjReportService  getListGps  Exception |{}", e.getMessage());
        }
        return gpsDTOS;
    }

    /**
     * 获取频次
     *
     * @param a
     * @return
     */
    private Integer getFrequency(Integer a) {
        Integer b = 1;
        if (a > 1000 && a <= 2000) {
            b = 10;
        } else if (a > 2000 && a <= 3000) {
            b = 20;
        } else if (a > 3000 && a <= 4000) {
            b = 30;
        } else if (a > 4000 && a <= 5000) {
            b = 40;
        } else if (a > 5000 && a <= 6000) {
            b = 50;
        } else {
            b = 60;
        }
        return b;
    }

    public IPage<TaxUpDataShippingNoteDTO> getTaxUpDataPageList(Page<TaxUpDataShippingNoteDTO> page,
                                                                QueryWrapper<TaxUpDataShippingNoteDTO> queryWrapper) {
        IPage<TaxUpDataShippingNoteDTO> pageList = hyShippingNoteMapper.getTaxUpDataPageList(page, queryWrapper);
        return pageList;
    }

}
